package cn.tedu.ivoscm.audit.service.impl;

import cn.tedu.ivoscm.application.mapper.ApplicationMapper;
import cn.tedu.ivoscm.application.pojo.entity.Application;
import cn.tedu.ivoscm.audit.mapper.AuditMapper;
import cn.tedu.ivoscm.audit.pojo.dto.AuditQuery;
import cn.tedu.ivoscm.audit.pojo.dto.AuditSaveParam;
import cn.tedu.ivoscm.audit.pojo.entity.Audit;
import cn.tedu.ivoscm.audit.pojo.vo.AuditVO;
import cn.tedu.ivoscm.audit.service.AuditService;
import cn.tedu.ivoscm.base.enums.ApplicationStatusEnum;
import cn.tedu.ivoscm.base.enums.AuditStatusEnum;
import cn.tedu.ivoscm.user.mapper.UserMapper;
import cn.tedu.ivoscm.user.pojo.dto.UserQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringJoiner;

@Transactional
@Slf4j
@Service
public class AuditServiceImpl implements AuditService {
    @Autowired
    private AuditMapper auditMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ApplicationMapper applicationMapper;

    @Override
    public void insertAudit(Application ap) {
        log.debug("为传入的申请单创建对应审批单业务，参数：{}", ap);
        List<Long> auditUserIdList = ap.getAuditUserIdList();
        for (int i = 0; i < auditUserIdList.size(); i++) {
            Audit audit = new Audit();
            audit.setApplicationId(ap.getId());
            audit.setAuditUserId(auditUserIdList.get(i));
            audit.setAuditSort(i);
            if (i == 0) {  // 第一个审批人，状态为“待我审核”
                audit.setAuditStatus(AuditStatusEnum.MY_PENDING.getCode());
            } else {  // 其他审批人都是“待他人审核”（其实也就俩）
                audit.setAuditStatus(AuditStatusEnum.PENDING.getCode());
            }
            audit.setCreateTime(new Date());
            auditMapper.insertAudit(audit);
        }
    }

    @Override
    public List<AuditVO> selectAuditByApplicationId(Long id) {
        log.debug("根据申请单ID查询审批单业务，参数：{}", id);
        List<AuditVO> auditList = auditMapper.selectAuditByApplicationId(id);
        return auditList;
    }

    @Override
    public List<AuditVO> select(AuditQuery aq) {
        log.debug("查询审批单业务，参数：{}", aq);
        List<AuditVO> list = auditMapper.select(aq);
        for (int i = 0; i < list.size(); i++) {
            AuditVO avo = list.get(i);
            // 自动补全
            assignAuditUserList(avo);
        }
        return list;
    }

    private void assignAuditUserList(AuditVO avo) {
        // 1. 准备空集合，分别保存当前传入审核单对应审批人的id与姓名
        List<Long> auditUserIdList = new ArrayList<>();
        List<String> auditUserNameList = new ArrayList<>();
        // 2. 通过申请单id再次查询审批单VO集合
        List<AuditVO> auditList = selectAuditByApplicationId(avo.getApplicationId());
        // 3. 遍历审批单VO
        for (AuditVO auditVO : auditList) {
            // 4. 获取审批人id，加入表
            Long auditUserId = auditVO.getAuditUserId();
            auditUserIdList.add(auditUserId);
            // 5. 查询其姓名
            UserQuery uq = new UserQuery();
            uq.setId(auditUserId);
            String username = userMapper.selectUser(uq).get(0).getUsername();
            auditUserNameList.add(username);
            // 6. 拼接工具拼接用户名
            StringJoiner sj = new StringJoiner(", ");
            for (String auditUsername : auditUserNameList) {
                sj.add(auditUsername);
            }
            // 7. 设置VO属性
            avo.setAuditUserIdList(auditUserIdList);
            avo.setAuditUserNameList(sj.toString());
        }
    }

    @Override
    public void update(AuditSaveParam asp) {
        log.debug("修改审批单业务，参数：{}", asp);
        Audit audit = new Audit();
        BeanUtils.copyProperties(asp, audit);
        audit.setUpdateTime(new Date());
        auditMapper.update(audit);
        // 更新对应的申请单的状态
        Application a = new Application();
        a.setId(asp.getApplicationId());
        a.setUpdateTime(new Date());
        // 注意：需要判断审批单的状态，针对不同状态要做不同操作
        if (AuditStatusEnum.AUDITED.getCode().equals(audit.getAuditStatus())) {
            // 同意
            // 继续查审批单
            AuditQuery aq = new AuditQuery();
            aq.setApplicationId(audit.getApplicationId());
            // 如果存在其他未审批的审批单，则申请单状态改为审核中，否则改为通过
            Integer count = auditMapper.selectCountNotAudit(aq);
            if (count > 0) {
                a.setStatus(ApplicationStatusEnum.AUDIT.getCode());
                // 更改下一个审批单的状态为“待我审核”
                aq.setAuditSort(audit.getAuditSort() + 1);
                System.out.println(aq);
                List<AuditVO> list = auditMapper.select(aq);
                if (list.size() > 0 && list.get(0) != null) {
                    AuditVO avo = list.get(0);
                    Audit audit2 = new Audit();
                    audit2.setId(avo.getId());
                    audit2.setAuditStatus(AuditStatusEnum.MY_PENDING.getCode());
                    auditMapper.update(audit2);
                }
                // 更改申请单的状态为“审核中”
                a.setStatus(ApplicationStatusEnum.AUDIT.getCode());
            } else {
                a.setStatus(ApplicationStatusEnum.AUDITED.getCode());
            }
        } else {
            // 驳回
            AuditQuery aq = new AuditQuery();
            aq.setApplicationId(audit.getApplicationId());
            List<AuditVO> auditVOList = auditMapper.select(aq);
            // 判断是否查询到数据，查到则遍历审批单，若查询状态为“待他人审核”，则删除审批单
            if (auditVOList != null && !auditVOList.isEmpty()) {
                for (int i = 0; i < auditVOList.size(); i++) {
                    AuditVO auditVO = auditVOList.get(i);
                    if (AuditStatusEnum.PENDING.getCode().equals(auditVO.getAuditStatus())){
                        auditMapper.deleteById(auditVO.getId());
                    }
                }
            }
            a.setStatus(ApplicationStatusEnum.REJECT.getCode());
            System.out.println(asp.getRejectReason());
            a.setRejectReason(asp.getRejectReason());
            a.setUpdateTime(new Date());
            System.out.println(a);
        }
        applicationMapper.update(a);
    }
}
